package org.wat.wcy.isi.mmazur.bp.io.model;

import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import org.wat.wcy.isi.mmazur.bp.io.BinaryObject;
import org.wat.wcy.isi.mmazur.bp.io.model.enums.NodeType;

public class Node extends BinaryObject {

	private final static int NAME_SIZE = 128;
	private final static int STATE_SIZE = 128;

	private IdDesc id;
	private String name;
	private NodeType type;
	private Node lane;
	private Node parent;
	private Loop loop;
	private GraphicsInfo graphicsInfo;
	private boolean transaction;
	private Map<String, String> additionalTags;
	private String objectState;

	public Node() {
		id = new IdDesc();
		additionalTags = new HashMap<String, String>();
		loop = new Loop();
		graphicsInfo = new GraphicsInfo(0, 0, 0, 0);
		objectState = "";
		name = "";
	}

	public String getObjectState() {
		return objectState;
	}

	public void setObjectState(String objectState) {
		this.objectState = objectState;
	}

	public IdDesc getId() {
		return id;
	}

	public void setId(IdDesc nodeId) {
		this.id = nodeId;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public boolean isTransaction() {
		return transaction;
	}

	public void setTransaction(boolean transatction) {
		this.transaction = transatction;
	}

	public NodeType getType() {
		return type;
	}

	public void setType(NodeType type) {
		this.type = type;
	}

	public Node getLane() {
		return lane;
	}

	public void setLane(Node laneId) {
		this.lane = laneId;
	}

	public Node getParent() {
		return parent;
	}

	public void setParent(Node parent) {
		this.parent = parent;
	}

	public Loop getLoop() {
		return loop;
	}

	public void setLoop(Loop loop) {
		this.loop = loop;
	}

	public GraphicsInfo getGraphicsInfo() {
		return graphicsInfo;
	}

	public void setGraphicsInfo(GraphicsInfo graphicsInfo) {
		this.graphicsInfo = graphicsInfo;
	}

	public Map<String, String> getAdditionalTags() {
		return additionalTags;
	}

	@Override
	public void write(RandomAccessFile raf) {
		try {
			// long begin = raf.getFilePointer();
			raf.writeInt(type.ordinal());
			id.write(raf);
			if (parent == null) {
				parent = new Node();
			}
			parent.getId().write(raf);
			if (lane == null) {
				lane = new Node();
			}
			lane.getId().write(raf);
			loop.write(raf);
			raf.write(Arrays.copyOf(name.getBytes(), NAME_SIZE));
			raf.write(Arrays.copyOf(objectState.getBytes(), STATE_SIZE));
			raf.writeBoolean(transaction);
			graphicsInfo.write(raf);
			// long end = raf.getFilePointer();
			// System.out.println("raf-  " + (end - begin));
			// private Rectangle graphicsInfo;
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void read(RandomAccessFile raf) {
		try {
			int index = raf.readInt();
			type = NodeType.values()[index];
			id.read(raf);
			parent = new Node();
			parent.getId().read(raf);
			lane = new Node();
			IdDesc laneId = new IdDesc();
			laneId.read(raf);
			lane.setId(laneId);
			loop.read(raf);
			byte b[] = new byte[NAME_SIZE];
			raf.read(b, 0, NAME_SIZE);
			name = new String(b).trim();
			b = new byte[STATE_SIZE];
			raf.read(b, 0, STATE_SIZE);
			objectState = new String(b).trim();
			transaction = raf.readBoolean();
			graphicsInfo.read(raf);
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Throwable t) {
			t.printStackTrace();
		}
	}

	public String toString() {
		StringBuffer strb = new StringBuffer();
		strb.append("Node[id=" + id.toString() + "] name=" + name + " ;type="
				+ type.toString());
		// strb.append("\n");
		// for (String s : additionalTags.keySet()) {
		// strb.append("  ");
		// strb.append(s + ":" + additionalTags.get(s));
		// strb.append("\n");
		// }
		return strb.toString();
	}

	public static int sizeOf() {
		return IdDesc.sizeOf() * 3 + NAME_SIZE + STATE_SIZE + (int) (Integer.SIZE / 8)
				+ Loop.sizeOf() + 1 /* Bool */+ GraphicsInfo.sizeOf();
	}
}
